import { Component, Input, OnInit } from '@angular/core';
import { DefaultService, Device } from '../../api';
import { ModalService } from '../modal.service';
import { ModalValue } from '../modal/modal.component';
import { ActivatedRoute, Router } from '@angular/router';
import 'rxjs/add/operator/toPromise';
import { UserService } from '../user.service';

declare let QRCode: any;
@Component({
  selector: 'app-device',
  templateUrl: './device.component.html',
  styleUrls: ['./device.component.css']
})
export class DeviceComponent implements OnInit {
  devices: Device[] = [];
  page = 1;
  limit = 12;
  maxPage: number;
  showTable: boolean = true;
  filterName: string;
  filterId: string;

  constructor(private api: DefaultService, private modal: ModalService, private router: Router, public user: UserService, private _route: ActivatedRoute) {
  }

  ngOnInit() {
    this.refresh();
  }

  refresh() {
    this.api.countDevices().subscribe(value => {
      this.maxPage = Math.ceil(value.count / this.limit);
    });
    this.api.listDevices((this.page - 1) * this.limit, this.limit
      , (this.filterId != '') ? this.filterId : null
      , (this.filterName != '') ? this.filterName : null).subscribe((devices: Device[]) => {
      this.devices = [];
      devices.forEach(value => {
        try {
          value['image'] = JSON.parse(value.description)['image'];
        } catch (e) {
        }
        this.devices.push(value);
      });
    });
  }

  add() {
    this.modal.modal(AddDeviceComponent, {'api':this.api}).then(value => {
      return this.api.putDevice(value).toPromise();
    }).then(status => {
      if (status.status == 1) {
        this.refresh();
      } else {
        alert(status.message);
      }
    });
  }

  edit(device: Device) {
    this.api.getDeviceDetail(device.deviceId).toPromise().then(value => {
      device['script'] = value.script;
      device['api'] = this.api;
      return this.modal.modal(EditDeviceComponent, device);
    }).then(value => {
      value['deviceId'] = device.deviceId;
      return this.api.postDevice(value).toPromise();
    }).then(status => {
      if (status.status == 1) {
        this.refresh();
      } else {
        alert(status.message);
      }
    });
  }

  showQrCode(deviceId:string){
    this.modal.modal(ShowQRCodeComponent,{'deviceId':deviceId});
  }

  detail(device: Device) {
    this.api.getState(device.deviceId).toPromise().then(value => {
      device['cState'] = (value.state == undefined || value.state == null || value.state == '') ? '设备未上传状态' : value.state;
      return this.modal.modal(DeviceDetail, device);
    }).then(value => {
      if (value['action'] == 'fClose') {
        this.api.forceClose(device.deviceId).subscribe(status => {
          if (status.status == 1) {
            this.refresh();
          } else {
            alert(status.message);
          }
        });
      } else if (value['action'] == 'setState') {
        this.api.postState(JSON.parse(value['desired']), device.deviceId).subscribe(status => {
          if (status.status == 1) {
            this.refresh();
          } else {
            alert(status.message);
          }
        });
      }else if(value['action'] == 'cmd'){
        this.api.postCMD(device.deviceId,value['base64']).subscribe(status => {
          if (status.status == 1) {
            this.refresh();
          } else {
            alert(status.message);
          }
        });
      }
    });
  }

  gotoSensors(id: string) {
    this.router.navigate(['sensor', id]);
  }

  goto(page: string | number) {
    if (Number(page) < 1 || Number(page) > this.maxPage) return;
    this.page = Number(page);
    this.refresh();
  }
}

@Component({
  template: `
    <div class="modal-header">
      创建设备
    </div>
    <div class="modal-body">
      <div class="form-group">
        <div class="row">
          <div class="col-lg-6">
            <label for="input-device-name">设备名称</label>
            <input id="input-device-name" type="text" class="form-control" [(ngModel)]="deviceName">
            <label>设备编号(选填)</label>
            <input class="form-control" [(ngModel)]="serialID">
            <label>厂家信息(选填)</label>
            <input class="form-control" [(ngModel)]="factoryInfo">
            <label>设备图片(选填)</label>
            <div class="input-group input-group-sm">
              <input class="form-control" type="file" (change)="onImageChange($event)">
              <span class="input-group-btn">
                <button class="btn btn-info btn-flat" (click)="uploadImage()">上传</button>
              </span>
            </div>
            <input *ngIf="image!==''" class="form-control" [value]="image" disabled>
            <label>设备位置(选填)</label>
            <input class="form-control" [(ngModel)]="location">
            <label>相关视频(选填)</label>
            <div class="input-group input-group-sm">
              <input class="form-control" type="file" (change)="onVideoChange($event)">
              <span class="input-group-btn">
                <button class="btn btn-info btn-flat" (click)="uploadVideo()">上传</button>
              </span>
            </div>
            <input *ngIf="video!==''" class="form-control" [value]="video" disabled>
            <label>相关信息(选填)</label>
            <textarea class="form-control" rows="6" [(ngModel)]="text"></textarea>
          </div>
          <div class="col-lg-6">
            <label for="input-device-script">绑定脚本</label>
            <textarea id="input-device-script" class="form-control" rows="21" [(ngModel)]="deviceScript"></textarea>
          </div>
        </div>
      </div>
    </div>
    <div class="modal-footer">
      <button class="btn btn-primary" (click)="finish()" [disabled]="deviceName==''">确定</button>
    </div>
  `
})
export class AddDeviceComponent implements ModalValue {
  @Input() callback: (any) => void;
  @Input() close: () => void;
  @Input() params: any;
  deviceName: string = '';
  deviceScript: string = '//default code\nfuncStorage(things,{});';
  serialID:string = '';
  image:string = '';
  location:string = '';
  video:string = '';
  text:string = '';
  factoryInfo:string = '';
  imageFile:File = null;
  videoFile:File = null;
  api:DefaultService = null;
  onInit() {
    this.api = this.params['api'];
  }

  onImageChange(event){
    const fileList = event.target.files;
    if(fileList.length>0){
      this.imageFile = fileList[0];
    }
  }

  onVideoChange(event){
    const fileList = event.target.files;
    if(fileList.length>0){
      this.videoFile = fileList[0];
    }
  }

  uploadImage(){
    const formData = new FormData();
    formData.append("uploadFile",this.imageFile,this.imageFile.name);
    this.api.postFile(formData).subscribe(value=>{
      this.image = this.api.basePath + '/file/' + value.message
    })
  }

  uploadVideo(){
    const formData = new FormData();
    formData.append("uploadFile",this.videoFile,this.videoFile.name);
    this.api.postFile(formData).subscribe(value=>{
      this.video = this.api.basePath + '/file/' + value.message
    })
  }

  finish() {
    const description = {'serialId':this.serialID,'factoryInfo':this.factoryInfo,'imageUrl':this.image,'location':this.location,'videoUrl':this.video,'text':this.text};
    this.callback({'name': this.deviceName, 'description': JSON.stringify(description), 'script': this.deviceScript});
    this.close();
  }
}
@Component({
  template: `
    <div class="modal-header">
      二维码
    </div>
    <div class="modal-body">
      <div id="qrcode"></div>
    </div>
    <div class="modal-footer">
      <button class="btn btn-primary" (click)="finish()">确定</button>
    </div>
  `
})
export class ShowQRCodeComponent implements ModalValue {
  @Input() callback: (any) => void;
  @Input() close: () => void;
  @Input() params: any;
  onInit(){
    new QRCode(document.getElementById("qrcode"), "http://link.hdussta.cn:7778/#/device/detail/"+this.params['deviceId']);
  }

  finish(){
    this.close();
  }
}

@Component({
  template: `
    <div class="modal-header">
      编辑设备
    </div>
    <div class="modal-body">
      <div class="form-group">
        <div class="row">
          <div class="col-lg-6">
            <label for="input-device-name">设备名称</label>
            <input id="input-device-name" type="text" class="form-control" [(ngModel)]="deviceName">
            <label>设备ID</label>
            <input class="form-control" [value]="deviceId" disabled>
            <label>设备秘钥</label>
            <input class="form-control" [value]="deviceSecret" disabled>
            <label>设备编号(选填)</label>
            <input class="form-control" [(ngModel)]="serialID">
            <label>厂家信息(选填)</label>
            <input class="form-control" [(ngModel)]="factoryInfo">
            <label>设备图片(选填)</label>
            <div class="input-group input-group-sm">
              <input class="form-control" type="file" (change)="onImageChange($event)">
              <span class="input-group-btn">
                <button class="btn btn-info btn-flat" (click)="uploadImage()">上传</button>
              </span>
            </div>
            <input *ngIf="image!=='' && image!==undefined && image!==null" class="form-control" [value]="image" disabled>
            <label>设备位置(选填)</label>
            <input class="form-control" [(ngModel)]="location">
            <label>相关视频(选填)</label>
            <div class="input-group input-group-sm">
              <input class="form-control" type="file" (change)="onVideoChange($event)">
              <span class="input-group-btn">
                <button class="btn btn-info btn-flat" (click)="uploadVideo()">上传</button>
              </span>
            </div>
            <input *ngIf="video!=='' && video!==null && video!==undefined" class="form-control" [value]="video" disabled>
            <label>相关信息(选填)</label>
            <textarea class="form-control" rows="6" [(ngModel)]="text"></textarea>
          </div>
          <div class="col-lg-6">
            <label for="input-device-script">绑定脚本</label>
            <textarea id="input-device-script" class="form-control" rows="24" [(ngModel)]="deviceScript"></textarea>
          </div>
        </div>
      </div>
    </div>
    <div class="modal-footer">
      <button class="btn btn-primary" (click)="finish()">确定</button>
    </div>
  `
})
export class EditDeviceComponent implements ModalValue {
  @Input() callback: (any) => void;
  @Input() close: () => void;
  @Input() params: any;
  deviceName: string;
  deviceScript: string;
  deviceId: string;
  deviceSecret: string;
  serialID:string = '';
  image:string = '';
  location:string = '';
  video:string = '';
  text:string = '';
  factoryInfo:string = '';
  imageFile:File = null;
  videoFile:File = null;
  api:DefaultService = null;
  onInit() {
    this.deviceName = this.params['name'];
    const description = JSON.parse(this.params['description']);
    this.serialID = description['serialId'];
    this.image = description['imageUrl'];
    this.location = description['location'];
    this.video = description['videoUrl'];
    this.text = description['text'];
    this.factoryInfo = description['factoryInfo'];
    this.deviceScript = this.params['script'];
    this.deviceSecret = this.params['secret'];
    this.deviceId = this.params['deviceId'];
    this.api = this.params['api'];
    if(this.deviceScript==''){
      this.deviceScript = `
       function onConnected(device,token){
         return token;
       }
       function onReceived(device,data){
         return 'OK';
       }
       function onDisconnected(device){
         return 'Disconnected';
       }
      `
    }
  }

  onImageChange(event){
    const fileList = event.target.files;
    if(fileList.length>0){
      this.imageFile = fileList[0];
    }
  }

  onVideoChange(event){
    const fileList = event.target.files;
    if(fileList.length>0){
      this.videoFile = fileList[0];
    }
  }

  uploadImage(){
    const formData = new FormData();
    formData.append("uploadFile",this.imageFile,this.imageFile.name);
    this.api.postFile(formData).subscribe(value=>{
      this.image = this.api.basePath + '/file/' + value.message
    })
  }

  uploadVideo(){
    const formData = new FormData();
    formData.append("uploadFile",this.videoFile,this.videoFile.name);
    this.api.postFile(formData).subscribe(value=>{
      this.video = this.api.basePath + '/file/' + value.message
    })
  }

  finish() {
    const description = {'serialId':this.serialID,'factoryInfo':this.factoryInfo,'imageUrl':this.image,'location':this.location,'videoUrl':this.video,'text':this.text};
    this.callback({'name': this.deviceName, 'description': JSON.stringify(description), 'script': this.deviceScript});
    this.close();
  }
}

@Component({
  template: `
    <div class="modal-header">
      {{name}}
    </div>
    <div class="modal-body">
      <div class="form-group">
        <label>是否在线</label>
        <input class="form-control" [value]="isOnline?'在线':'离线'" disabled>
        <label for="current-state">当前状态</label>
        <textarea id="current-state" class="form-control" rows="4" disabled [value]="currentState"></textarea>
        <label for="input-desired-state">预期状态</label>
        <textarea id="input-desired-state" class="form-control" rows="4" [(ngModel)]="desiredState"></textarea>
        <div>
          <label>发送16进制指令</label>
          <input class="form-control" style="margin-bottom: 5px" [(ngModel)]="cmdHex">
          <button class="btn btn-info" (click)="sendCmd()" >发送</button>
        </div>
        <label>其他控制</label>
        <div class="btn-toolbar">
          <button class="btn btn-danger" (click)="forceClose()" [disabled]="!isOnline">强制下线</button>
        </div>
      </div>
    </div>
    <div class="modal-footer">
      <button class="btn btn-primary" (click)="finish()">确定</button>
    </div>
  `
})
export class DeviceDetail implements ModalValue {
  @Input() callback: (any) => void;
  @Input() close: () => void;
  @Input() params: any;

  name: string;
  isOnline: boolean;
  currentState: string;
  desiredState: string = '';
  cmdHex:string = '';
  onInit() {
    const device = <Device> this.params;
    this.name = device.name;
    this.isOnline = device.state == 1;
    this.currentState = device['cState'];

  }

  forceClose() {
    this.callback({'action': 'fClose'});
    this.close();
  }

  sendCmd(){
    const raw = DeviceDetail.parseHexString(this.cmdHex);
    const base64String = btoa(String.fromCharCode.apply(null, new Uint8Array(raw)));
    this.callback({'action': 'cmd','base64':base64String});
    this.close();
  }

  finish() {
    if (this.desiredState != null && this.desiredState != '')
      this.callback({'action': 'setState', 'desired': this.desiredState});
    this.close();
  }

  private static parseHexString(str1) {
    var hex  = str1.toString();
    var str = [];
    for (var n = 0; n < hex.length; n += 2) {
      str.push(parseInt(hex.substr(n, 2), 16));
    }
    return str;
  }
}
